﻿//  Copyright © 2009-2010 by Rhy A. Mednick
//  All rights reserved.
//  http://rhyduino.codeplex.com
//  
//  Redistribution and use in source and binary forms, with or without modification, 
//  are permitted provided that the following conditions are met:
//  
//  * Redistributions of source code must retain the above copyright notice, this list 
//    of conditions and the following disclaimer.
//  
//  * Redistributions in binary form must reproduce the above copyright notice, this 
//    list of conditions and the following disclaimer in the documentation and/or other 
//    materials provided with the distribution.
//  
//  * Neither the name of Rhy A. Mednick nor the names of its contributors may be used 
//    to endorse or promote products derived from this software without specific prior 
//    written permission.
//  
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
//  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
//  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
//  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
//  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
//  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
//  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
//  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
//  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
//  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
//  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using System;
using System.Collections.Generic;
using TracerX.Forms;

namespace TracerX.Viewer
{
    internal static class MethodObjects
    {
        // Lock this when accessing the AllMethods collection.
        public static object Lock = new object();

        // List of all created MethodObjects.
        public static List<MethodObject> AllMethods = new List<MethodObject>();
        private static int _invisibleCount;

        /// <summary>
        ///   Are all methods visible?
        /// </summary>
        public static bool AllVisible
        {
            get { lock (Lock) return _invisibleCount == 0; }
        }

        public static void IncrementInvisibleCount()
        {
            lock (Lock)
            {
                if (++_invisibleCount == 1)
                {
                    OnAllVisibleChanged();
                }
            }
        }

        public static void DecrementInvisibleCount()
        {
            lock (Lock)
            {
                if (--_invisibleCount == 0)
                {
                    OnAllVisibleChanged();
                }
            }
        }

        /// <summary>
        ///   Event called when AllVisible changes.
        /// </summary>
        public static event EventHandler AllVisibleChanged;

        private static void OnAllVisibleChanged()
        {
            if (AllVisibleChanged != null)
            {
                AllVisibleChanged(null, null);
            }
        }

        // Count the visible methods in AllMethods, set the internal count (invisibleCount) accordingly, 
        // and raise the AllVisibleChanged event if the new count differs from the current count.
        public static void RecountMethods()
        {
            lock (Lock)
            {
                var oldCount = _invisibleCount;
                _invisibleCount = 0;

                foreach (var m in AllMethods)
                {
                    if (!m.Visible) ++_invisibleCount;
                }

                if (_invisibleCount != oldCount)
                {
                    if (_invisibleCount == 0 || oldCount == 0)
                    {
                        OnAllVisibleChanged();
                    }
                }
            }
        }

        public static void ShowAllMethods()
        {
            lock (Lock)
            {
                foreach (var l in AllMethods)
                {
                    l.Visible = true;
                }
            }
        }

        public static void HideAllMethods()
        {
            lock (Lock)
            {
                foreach (var l in AllMethods)
                {
                    l.Visible = false;
                }
            }
        }
    }

    internal class MethodObject : IFilterable
    {
        protected bool _visible = true;

        #region IFilterable Members

        public string Name { get; set; }

        public ColorRulesDialog.ColorPair Colors { get; set; }

        /// <summary>
        ///   Is the output from this logger visible?
        /// </summary>
        public bool Visible
        {
            get { return _visible; }
            set
            {
                if (_visible != value)
                {
                    _visible = value;

                    // Track the number of filtered loggers.
                    if (_visible)
                    {
                        MethodObjects.DecrementInvisibleCount();
                    }
                    else
                    {
                        MethodObjects.IncrementInvisibleCount();
                    }
                }
            }
        }

        #endregion
    }
}